Take-home Exercise 3

Reveal the impact of COVID-19 on the stock prices of top 40 companies in Singapore by market capitalisation.

Sun Shengmei https://www.linkedin.com/in/shengmei-sun-9b262656/?originalSubdomain=sg (SMU MITB)https://scis.smu.edu.sg/master-it-business
2022-02-27

The Task

  1. Script stock prices of top 40 companies in Singapore by market capitalization between 1st January 2020 - 31st December 2021 by using tidyquant R package.

  2. Using either calender heatmap or horizon graph, prepare a data visualization showing the historical stock prices by the top 40 companies in Singapore by market capitalization.

Installing and Loading the Required Libraries

The code chunk below is to install the packages needed.

packages = c('tidyquant', 'tidyverse', 'ggHoriPlot', 'ggTimeSeries', 'kableExtra', 'ggthemes', 'plotly')

for(p in packages){library
  if(!require(p, character.only = T)){
    install.packages(p)
  }
  library(p, character.only = T)
}

Data Scraping

The symbols of the top 40 companies in Singapore by market capitalization was downloaded as companiesmarketcap.com - Largest companies in Singapore by market capitalization.cs. This csv data was imported using below code.

symbol_table <- read_csv("data/companiesmarketcap.com - Largest companies in Singapore by market capitalization.csv") %>%
  rename(symbol = Symbol)

Below code chunk is to script the stocks data from Yahoo Finance.

from_date = "2020-01-01"
to_date = "2021-12-01"

stock_selected = c(symbol_table$symbol[1:40]) 

Top40_Name = c(symbol_table$Name[1:40]) 

stock_data_daily = tq_get(stock_selected,
               get = "stock.prices",
               from = from_date,
               to = to_date)

kable(head(stock_data_daily)) %>%
   kable_styling()
symbol date open high low close volume adjusted
SE 2020-01-02 41.00 41.190 39.460 40.04 5857000 40.04
SE 2020-01-03 39.44 40.650 39.400 40.49 5237800 40.49
SE 2020-01-06 40.07 41.030 40.029 40.48 4049200 40.48
SE 2020-01-07 40.50 41.800 40.350 41.01 3947600 41.01
SE 2020-01-08 41.00 41.389 40.055 40.16 3200800 40.16
SE 2020-01-09 40.79 40.900 40.040 40.53 3129700 40.53

Let’s now join ‘stock_data_daily’ with ‘symbol’ to include the company name in the data tibble.

stock_data_daily1 <- stock_data_daily %>%
  left_join(symbol_table,
            by = "symbol")

Next, we want to order the stock in descending order by the market capitalization value using order().

stock_data_daily1 <- stock_data_daily1[order(-stock_data_daily1$marketcap),]

Alternative method is as below:

stock_data_daily1 <- stock_data_daily1 %>%
  mutate(Name =  factor(Name, levels = Top40_Name)) %>%
  arrange(Name)

kable(head(stock_data_daily1)) %>%
     kable_styling()
symbol date open high low close volume adjusted Rank Name marketcap price (USD) country
SE 2020-01-02 41.00 41.190 39.460 40.04 5857000 40.04 1 Sea (Garena) 76666667008 137.46 Singapore
SE 2020-01-03 39.44 40.650 39.400 40.49 5237800 40.49 1 Sea (Garena) 76666667008 137.46 Singapore
SE 2020-01-06 40.07 41.030 40.029 40.48 4049200 40.48 1 Sea (Garena) 76666667008 137.46 Singapore
SE 2020-01-07 40.50 41.800 40.350 41.01 3947600 41.01 1 Sea (Garena) 76666667008 137.46 Singapore
SE 2020-01-08 41.00 41.389 40.055 40.16 3200800 40.16 1 Sea (Garena) 76666667008 137.46 Singapore
SE 2020-01-09 40.79 40.900 40.040 40.53 3129700 40.53 1 Sea (Garena) 76666667008 137.46 Singapore

Now, our dataset ‘stock_data_daily1’ is ready for visualization.

Data Visualization

Calender Heatmap

A calendar heatmap is a great way to visualise daily data. Its structure makes it easy to detect weekly, monthly, or seasonal patterns.

We firstly create a function to make a calendar heatmap and set Name as the variable, so that we don’t need to repeat the steps when plotting for all the 40 companies. Later, we will loop through all the values in Name column to create the corresponding plots.

calendar_heatmap <- function(df, var) {
ggplot_calendar_heatmap(
   df %>% filter(Name ==var),
   'date',
   'close',   
   dayBorderSize = 0.25, 
   dayBorderColour = "black",
   monthBorderSize = 1, 
   monthBorderColour = "black",
   monthBorderLineEnd = "round") +
    xlab('') + 
    ylab('') + 
    labs(title = paste(var, "Stock Close Price (SGD/share)"))+
    scale_fill_continuous(low = "red", high = "green")+ 
    theme(plot.title = element_text(size = rel(1), hjust=0.5, face = "bold"),
          panel.background = element_rect(fill = NA),
          panel.grid.major = element_line(colour = "grey90"),
          panel.border = element_rect(linetype = "solid", fill = NA),
          strip.background = element_rect(colour = "black"),
          strip.text.x = element_text(colour = "black", size = rel(1), face = "bold"),
          legend.title = element_text(face = "bold"),
          axis.text = element_text(colour = "black", size = rel(0.8), face = "bold"))


}

Next, we loop through Name var, create plots and store them in a list using purrr::map(). Then, we display all plots with purrr::walk().

plot_list <- unique(stock_data_daily1$Name) %>% 
  purrr::set_names() %>% 
  purrr::map( ~ calendar_heatmap(stock_data_daily1, .x))
purrr::walk(plot_list, print)

Below is to explore if above calendar heatmap works with ggplotly() to make it interactive. We can see that this interactive plot works.

p <- ggplot_calendar_heatmap(
   stock_data_daily1 %>% filter(Name == 'DBS'),
   'date',
   'close',   
   dayBorderSize = 0.25, 
   dayBorderColour = "black",
   monthBorderSize = 1, 
   monthBorderColour = "black",
   monthBorderLineEnd = "round") +
    xlab('') + 
    ylab('') + 
    labs(title = paste('DBS', "Stock Close Price (SGD/share)"))+
    scale_fill_continuous(low = "red", high = "green")+ 
    theme(plot.title = element_text(size = 8, hjust=0.5, face = "bold"),
          panel.background = element_rect(fill = NA),
          panel.grid.major = element_line(colour = "grey90"),
          panel.border = element_rect(linetype = "solid", fill = NA),
          strip.background = element_rect(colour = "black"),
          strip.text.x = element_text(colour = "black", size = 8, face = "bold"),
          legend.title = element_text(face = "bold"),
          axis.text = element_text(colour = "black", size = 8, face = "bold"))


ggplotly(p, height = 250, width=900)

Horizon Graph

Horizon Graph compact the area chart by slicing it horizontally, and then then shifting the slices to baseline zero. It’s like a combo area chart and heatmap. The figure below shows a horizon plot using the ggHoriplot package.

ggplot() +
  geom_horizon(aes(date, close),
               data = stock_data_daily1,
               origin = 'mean',
               horizonscale = 6) +
  scale_fill_hcl(palette = 'RdBu') +  
  facet_grid(Name~.)+
   theme_few() +
   theme(panel.spacing.y=unit(0, "lines"),
    plot.title = element_text(size=13, face = "bold"),
    plot.subtitle = element_text(size=9, face = "bold"),
    strip.text.y = element_text(size = 9, angle = 0, hjust = 0, face = "bold"),
    axis.text.y = element_blank(),
    axis.text.x = element_text(size=9, angle = 90, face = "bold"),
    axis.title.y = element_blank(),
    axis.title.x = element_blank(),
    axis.ticks.y = element_blank(),
    panel.border = element_blank(),
    legend.position="none") +
   scale_x_date(expand=c(0,0), 
               date_breaks = "1 month", 
               date_labels = "%b-%y",
               limit=c(as.Date("2020-01-01"),as.Date("2021-12-31"))) +
  ggtitle('Daily Stock Price of Top 40 Companies in Singapore (SGD/share), 2020 to 2021',
          'Ranked by Market Capitalisation')

Below is to explore if above horizon graph works with ggplotly() wrapper to make it interactive.

H <- ggplot() +

  geom_horizon(aes(date, close),
               data = stock_data_daily1,
               origin = 'mean',
               horizonscale = 6) +
  scale_fill_hcl(palette = 'RdBu') +  
  facet_grid(Name~.)+
   theme_few() +
   theme(panel.spacing.y=unit(0, "lines"),
    plot.title = element_text(size=13, face = "bold"),
    plot.subtitle = element_text(size=9, face = "bold"),
    strip.text.y = element_text(size = 9, angle = 0, hjust = 0, face = "bold"),
    axis.text.y = element_blank(),
    axis.text.x = element_text(size=9, angle = 90, face = "bold"),
    axis.title.y = element_blank(),
    axis.title.x = element_blank(),
    axis.ticks.y = element_blank(),
    panel.border = element_blank(),
    legend.position="none") +
   scale_x_date(expand=c(0,0), 
               date_breaks = "1 month", 
               date_labels = "%b-%y",
               limit=c(as.Date("2020-01-01"),as.Date("2021-12-31"))) +
  ggtitle('Daily Stock Price of Top 40 Companies in Singapore (SGD/share), 2020 to 2021',
          'Ranked by Market Capitalisation') 


ggplotly(H)

We can see that this interactive plot doesn’t work. Only x and y axis and title are displayed.

Conclusions

Comparision between Calendar Heatmap and Horizon Graph

Reference

Using R to Scrape Financial Dataset

Plotting multiple graphs in R

ggHoriPlot: build horizon plots in ggplot2